/*
	Copyright 2006-2015 The QElectroTech Team
	This file is part of QElectroTech.

	QElectroTech is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.

	QElectroTech is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTAvBILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with QElectroTech.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "qetsingleapplication.h"
#include <QLocalSocket>

const int QETSingleApplication::timeout_ = 10000;

/**
	Constructeur
	@param argc Nombre d'arguments passes au programme par le systeme
	@param argv Tableau des arguments passes au programme par le systeme
	@param unique_key Cle unique
*/
QETSingleApplication::QETSingleApplication (int &argc, char **argv, const QString unique_key) :
    QApplication (argc, argv),
    unique_key_ (unique_key)
{
    // verifie s'il y a un segment de memoire partage correspondant a la cle unique
#if defined (Q_OS_OS2)
#define QT_NO_SHAREDMEMORY
    {
#else
    shared_memory_.setKey (unique_key_);
    if (shared_memory_.attach())
    {
        // oui : l'application est deja en cours d'execution
        is_running_ = true;
    }
    else
    {
        // non : il s'agit du premier demarrage de l'application pour cette cle unique
        is_running_ = false;

        // initialisation du segment de memoire partage
        if (!shared_memory_.create (1))
        {
            qDebug() << "QETSingleApplication::QETSingleApplication() : Impossible de cr\351er l'instance unique" << qPrintable (unique_key_);
            return;
        }
#endif
        // initialisation d'un serveur local pour recevoir les messages des autres instances
        local_server_ = new QLocalServer (this);
        connect (local_server_, SIGNAL (newConnection()), this, SLOT (receiveMessage()));
        // la cle unique est egalement utilise pour le serveur
        local_server_ -> listen (unique_key_);
    }
}

/**
	Destructeur
*/
QETSingleApplication::~QETSingleApplication()
{
}

/**
	Slot gerant la reception des messages.
	Lorsque l'application recoit un message, ce slot emet le signal
	messageAvailable avec le message recu.
*/
void QETSingleApplication::receiveMessage()
{
    QLocalSocket *local_socket = local_server_ -> nextPendingConnection();
    if (!local_socket -> waitForReadyRead (timeout_))
    {
        qDebug() << "QETSingleApplication::receiveMessage() :" << qPrintable (local_socket -> errorString()) << "(" << qPrintable (unique_key_) << ")";
        return;
    }
    QByteArray byteArray = local_socket -> readAll();
    QString message = QString::fromUtf8 (byteArray.constData());
    emit (messageAvailable (message));
    local_socket -> disconnectFromServer();
}

/**
	@return true si l'application est deja en cours d'execution
*/
bool QETSingleApplication::isRunning()
{
    return (is_running_);
}

/**
	Envoie un message a l'application. Si celle-ci n'est pas en cours
	d'execution, cette methode ne fait rien.
	@param message Message a transmettre a l'application
	@return true si le message a ete tranmis, false sinon
*/
bool QETSingleApplication::sendMessage (const QString &message)
{
    // l'application doit etre en cours d'execution
    if (!is_running_)
    {
        return (false);
    }

    // se connecte a l'application, avec gestion du timeout
    QLocalSocket local_socket (this);
    local_socket.connectToServer (unique_key_, QIODevice::WriteOnly);
    if (!local_socket.waitForConnected (timeout_))
    {
        qDebug() << "QETSingleApplication::sendMessage() :" << qPrintable (local_socket.errorString()) << "(" << qPrintable (unique_key_) << ")";
        return (false);
    }

    // envoi du message, avec gestion du timeout
    local_socket.write (message.toUtf8());
    if (!local_socket.waitForBytesWritten (timeout_))
    {
        qDebug() << "QETSingleApplication::sendMessage() :" << qPrintable (local_socket.errorString()) << "(" << qPrintable (unique_key_) << ")";
        return (false);
    }

    // deconnexion
    local_socket.disconnectFromServer();
    return (true);
}
